package com.zscat.mallplus.ums.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zscat.mallplus.exception.ApiMallPlusException;
import com.zscat.mallplus.exception.BusinessMallException;
import com.zscat.mallplus.single.ApiBaseAction;
import com.zscat.mallplus.sys.entity.SysUser;
import com.zscat.mallplus.sys.mapper.SysAppletSetMapper;
import com.zscat.mallplus.sys.mapper.SysUserMapper;
import com.zscat.mallplus.ums.entity.SysAppletSet;
import com.zscat.mallplus.ums.entity.UmsMember;
import com.zscat.mallplus.ums.mapper.UmsMemberMapper;
import com.zscat.mallplus.ums.service.IUmsMemberService;
import com.zscat.mallplus.ums.service.RedisService;
import com.zscat.mallplus.utils.*;
import com.zscat.mallplus.vo.ApiContext;
import com.zscat.mallplus.vo.AppletLoginParam;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author mallplus
 * @since 2019-04-19
 */
@Slf4j
@Service
public class UmsMemberServiceImpl extends ServiceImpl<UmsMemberMapper, UmsMember> implements IUmsMemberService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UmsMemberServiceImpl.class);
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private UmsMemberMapper memberMapper;
    @Resource
    private BCryptPasswordEncoder passwordEncoder;
    @Resource
    private RedisService redisService;
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Value("${redis.key.prefix.authCode}")
    private String REDIS_KEY_PREFIX_AUTH_CODE;
    @Value("${authCode.expire.seconds}")
    private Long AUTH_CODE_EXPIRE_SECONDS;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Value("${aliyun.sms.expire-minute:1}")
    private Integer expireMinute;
    @Value("${aliyun.sms.day-count:30}")
    private Integer dayCount;

    @Value("${wxpay.appId}")
    private String wxH5Appid;
    @Value("${wxpay.appSecret}")
    private String wxH5Secret;

    @Resource
    private SysAppletSetMapper appletSetMapper;

    private OkHttpClient okHttpClient = new OkHttpClient();

    @Resource
    private ApiContext apiContext;

    @Override
    public Map<String, Object> loginByWeixinPage(String code) throws BusinessMallException {
        //H5 微信公众号网页登录
        LOGGER.info("appid:{},appsecret:{}", wxH5Appid, wxH5Secret);
        try {
            String json = okHttpClient.newCall(
                    new Request.Builder().url("https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                            + wxH5Appid + "&secret=" + wxH5Secret + "&code=" + code + "&grant_type=authorization_code").build()).execute().body().string();
            com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(json);
            Integer errcode = jsonObject.getInteger("errcode");
            LOGGER.info("授权信息:{}", JSON.toJSONString(jsonObject));
            Map<String, Object> resultObj = new HashMap<>();
            String token = null;
            if (errcode == null || errcode == 0) {
                String openid = jsonObject.getString("openid");
                QueryWrapper qw = new QueryWrapper();
                qw.eq("weixin_openid", openid);
                List<UmsMember> userDOS = memberMapper.selectList(qw);
                if (!CollectionUtils.isEmpty(userDOS)) {
                    //若用户已经注册，则直接返回用户
                    UmsMember member = userDOS.get(0);
                    token = jwtTokenUtil.generateToken(member.getUsername());
                    resultObj.put("userId", member.getId());
                    resultObj.put("userInfo", member);
                } else {
                    String userAccessToken = jsonObject.getString("access_token");
                    //通过用户AccessToken换取用户信息
                    String userInfoJson = okHttpClient.newCall(
                            new Request.Builder().url("https://api.weixin.qq.com/sns/userinfo?access_token="
                                    + userAccessToken + "&openid=" + openid + "&lang=zh_CN").build()).execute().body().string();
                    com.alibaba.fastjson.JSONObject userInfoJsonObject = com.alibaba.fastjson.JSONObject.parseObject(userInfoJson);
                    Date now = new Date();
                    UmsMember newUserDO = new UmsMember();
                    String nickname = EmojiFilter.filterEmoji(userInfoJsonObject.getString("nickname"));
                    newUserDO.setUsername("M_" + nickname);
                    newUserDO.setNickname(nickname);
                    String avatar = userInfoJsonObject.getString("headimgurl");
                    newUserDO.setAvatar(avatar);
                    newUserDO.setIcon(avatar);
                    newUserDO.setGender(userInfoJsonObject.getInteger("sex"));
                    newUserDO.setWeixinOpenid(openid);
                    newUserDO.setCreateTime(now);
                    newUserDO.setCity(userInfoJsonObject.getString("city"));
                    memberMapper.insert(newUserDO);
                    //这一步是为了封装上数据库上配置的默认值
                    token = jwtTokenUtil.generateToken(newUserDO.getUsername());
                    resultObj.put("isNew", true);
                    resultObj.put("userId", newUserDO.getId());
                    resultObj.put("userInfo", newUserDO);
                }
            }
            if (StringUtils.isEmpty(token)) {
                return ApiBaseAction.toResponsFail("登录失败");
            }
            resultObj.put("tokenHead", tokenHead);
            resultObj.put("token", token);
            return resultObj;
        } catch (IOException ie) {
            ie.printStackTrace();
            throw new BusinessMallException(ie.getMessage());
        } catch (ApiMallPlusException e) {
            e.printStackTrace();
            throw new BusinessMallException(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessMallException(e.getMessage());
        }
    }

    @Override
    public SysUser getUserByUsername(String username) {
        SysUser sysUser = new SysUser();
        sysUser.setUsername(username);
        return sysUserMapper.selectOne(new QueryWrapper<>(sysUser));
    }

    @Override
    public UmsMember getByUsername(String username) {
        UmsMember member = new UmsMember();
        member.setUsername(username);
        return memberMapper.selectOne(new QueryWrapper<>(member));
    }

    @Override
    public UmsMember getById(Long id) {
        return memberMapper.selectById(id);
    }

    @Override
    public Object simpleReg(String phone, String password, String confimpassword) {
        //没有该用户进行添加操作
        UmsMember user = new UmsMember();
        user.setUsername(phone);
        user.setPhone(phone);
        user.setPassword(password);
        user.setConfimpassword(confimpassword);


        if (!user.getPassword().equals(user.getConfimpassword())) {
            return new CommonResult().failed("密码不一致");
        }
        //查询是否已有该用户

        UmsMember queryM = new UmsMember();
        queryM.setUsername(user.getUsername());

        UmsMember umsMembers = memberMapper.selectOne(new QueryWrapper<>(queryM));
        if (umsMembers != null) {
            return new CommonResult().failed("该用户已经存在");
        }
        //没有该用户进行添加操作

        UmsMember umsMember = new UmsMember();
        umsMember.setMemberLevelId(4L);
        umsMember.setUsername(user.getUsername());
        umsMember.setPhone(user.getPhone());
        umsMember.setPassword(passwordEncoder.encode(user.getPassword()));
        umsMember.setCreateTime(new Date());
        umsMember.setStatus(1);

        memberMapper.insert(umsMember);
        umsMember.setPassword(null);
        return new CommonResult().success("注册成功", "注册成功");
    }

    @Override
    public UmsMember queryByOpenId(String openId) {
        UmsMember member = new UmsMember();
        member.setWeixinOpenid(openId);
        QueryWrapper qw = new QueryWrapper();
        qw.orderByDesc("id");
        qw.setEntity(member);
        List<UmsMember> members = memberMapper.selectList(qw);
        if(null != members && !members.isEmpty()){
            return members.get(0);
        }
        return null;
    }

    @Override
    public Object loginByWeixin(AppletLoginParam req) {
        try {
            apiContext.setCurrentProviderId(req.getStoreId());
            QueryWrapper qw = new QueryWrapper();
            SysAppletSet appletSet = appletSetMapper.selectOne(qw);
            String codeH = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=STAT#wechat_redirect";

            String code = req.getCode();
            if (StringUtils.isEmpty(code)) {
                log.error("code ie empty");
                return ApiBaseAction.toResponsFail("code ie empty");
            }
            String userInfos = req.getUserInfo();

            String signature = req.getSignature();

            Map<String, Object> me = JsonUtils.readJsonToMap(userInfos);
            if (null == me) {
                return ApiBaseAction.toResponsFail("登录失败 userInfos is null");
            }

            Map<String, Object> resultObj = new HashMap<String, Object>();

            String webAccessTokenhttps = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
            log.info("appid:{},js_code:{}", appletSet.getAppid(), code);
            //获取openid
            String requestUrl = String.format(webAccessTokenhttps,
                    appletSet.getAppid(),
                    appletSet.getAppsecret(),
                    code);

            JSONObject sessionData = CommonUtil.httpsRequest(requestUrl, "GET", null);
            log.info("sessionData:{}", JSON.toJSONString(sessionData));
            if (null == sessionData || (sessionData.containsKey("openid") && StringUtils.isEmpty(sessionData.getString("openid")))) {
                return ApiBaseAction.toResponsFail("登录失败openid is empty");
            }
            //验证用户信息完整性
            String sessionKey = sessionData.getString("session_key");
            String sha1 = CommonUtil.getSha1(userInfos + sessionKey);
//            String sha1 = DigestUtils.sha1Hex(userInfos + sessionData.getString("session_key"));
//            if (!signature.equals(sha1)) {
//                return ApiBaseAction.toResponsFail("登录失败,验证用户信息完整性");
//            }
            UmsMember userVo = this.queryByOpenId(sessionData.getString("openid"));
            String token = null;
            if (null == userVo) {
                UmsMember umsMember = new UmsMember();
                umsMember.setUsername("wxapplet" + CharUtil.getRandomString(12));
                umsMember.setSourceType(2);
                umsMember.setPassword(passwordEncoder.encode("123456"));
                umsMember.setCreateTime(new Date());
                umsMember.setStatus(1);
                umsMember.setBlance(new BigDecimal(10000));
                umsMember.setIntegration(0);
                umsMember.setMemberLevelId(4L);
                umsMember.setAvatar(req.getCloudID());
                umsMember.setCity(me.get("country").toString() + "-" + me.get("province").toString() + "-" + me.get("city").toString());
//                umsMember.setStoreId(req.getStoreId());
                umsMember.setGender((Integer) me.get("gender"));
                umsMember.setHistoryIntegration(0);
                umsMember.setWeixinOpenid(sessionData.getString("openid"));
                if (StringUtils.isEmpty(me.get("avatarUrl").toString())) {
                    //会员头像(默认头像)
                    umsMember.setIcon("/upload/img/avatar/01.jpg");
                } else {
                    umsMember.setIcon(me.get("avatarUrl").toString());
                }
                // umsMember.setGender(Integer.parseInt(me.get("gender")));
                umsMember.setNickname(EmojiFilter.filterEmoji(me.get("nickName").toString()));
                memberMapper.insert(umsMember);
                token = jwtTokenUtil.generateToken(umsMember.getUsername());
                resultObj.put("userId", umsMember.getId());
                resultObj.put("userInfo", umsMember);

            } else {
                token = jwtTokenUtil.generateToken(userVo.getUsername());
                resultObj.put("userId", userVo.getId());
                resultObj.put("userInfo", userVo);
            }


            if (StringUtils.isEmpty(token)) {
                return ApiBaseAction.toResponsFail("登录失败");
            }
            resultObj.put("tokenHead", tokenHead);
            resultObj.put("token", token);
            resultObj.put("sessionKey",sessionKey);
            resultObj.put("appId",appletSet.getAppid());
            return ApiBaseAction.toResponsSuccess(resultObj);
        } catch (ApiMallPlusException e) {
            e.printStackTrace();
            return ApiBaseAction.toResponsFail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return ApiBaseAction.toResponsFail(e.getMessage());
        }

    }

    @Override
    public String refreshToken(String oldToken) {
        String token = oldToken.substring(tokenHead.length());
        if (jwtTokenUtil.canRefresh(token)) {
            return jwtTokenUtil.refreshToken(token);
        }
        return null;
    }
}

